package net.mikoo.seals.biz.service.impl;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneOffset;
import java.util.Date;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;

import net.mikoo.seals.biz.common.BaseServices;
import net.mikoo.seals.biz.mapper.ApplyMapper;
import net.mikoo.seals.biz.mapper.CustosMapper;
import net.mikoo.seals.biz.mapper.DevicesMapper;
import net.mikoo.seals.biz.mapper.DevicesTakeMapper;
import net.mikoo.seals.biz.mapper.PartyMapper;
import net.mikoo.seals.biz.mapper.SealMapper;
import net.mikoo.seals.biz.service.DevicesTakeService;
import net.mikoo.seals.common.enums.CustosStatusEnum;
import net.mikoo.seals.common.enums.CustosTypeEnum;
import net.mikoo.seals.common.enums.DevicesStatusEnum;
import net.mikoo.seals.common.enums.TakeStatusEnum;
import net.mikoo.seals.common.exception.ParametersException;
import net.mikoo.seals.common.model.PageModel;
import net.mikoo.seals.model.Apply;
import net.mikoo.seals.model.Custos;
import net.mikoo.seals.model.CustosQuery;
import net.mikoo.seals.model.Devices;
import net.mikoo.seals.model.DevicesQuery;
import net.mikoo.seals.model.DevicesTake;
import net.mikoo.seals.model.DevicesTakeQuery;
import net.mikoo.seals.model.Party;
import net.mikoo.seals.model.Seal;

@Service
public class DevicesTakeServiceImpl extends BaseServices implements DevicesTakeService {

	@Autowired
	private DevicesTakeMapper devicesTakeMapper;
	
	@Autowired
	private DevicesMapper devicesMapper;
	
	@Autowired
	private SealMapper sealMapper;
	
	@Autowired
	private CustosMapper custosMapper;
	
	@Autowired
	private ApplyMapper applyMapper;
	
	@Autowired
	private PartyMapper partyMapper;

	@Override
	public PageModel<DevicesTake> getPageByQuery(DevicesTakeQuery query) {
		
		List<DevicesTake> datas = devicesTakeMapper.selectPageByQuery(query);
		Integer total = devicesTakeMapper.countPageByQuery(query);
		PageModel<DevicesTake> pm = new PageModel<>(total, datas);
		
		return pm;
	}
	
	@Override
	public List<DevicesTake> getListByQuery(DevicesTakeQuery query) {
		if(query == null) {
			throw new ParametersException("query");
		}
		return devicesTakeMapper.selectListByQuery(query);
	}

	@Override
	public DevicesTake getById(Long id) {
		if(id == null) {
			throw new ParametersException("id");
		}
		return devicesTakeMapper.selectInfoById(id);
	}

	@Override
	public DevicesTake getInfoByQuery(DevicesTakeQuery query) {
		
		if(query == null) {
			throw new ParametersException("query is null");
		}
		
		return devicesTakeMapper.selectInfoByQuery(query);
	}

	@Override
	public void receive(DevicesTake devicesTake) {
		
		if(devicesTake == null) {
			throw new ParametersException("devicesTake is null");
		}
		
		if(devicesTake.getDevicesTakeId() == null) {
			throw new ParametersException("DevicesTakeId is null");
		}
		
		if(devicesTake.getDevicesId() == null) {
			throw new ParametersException("请选择设备");
		}
		
		DevicesTake extisTake = devicesTakeMapper.selectInfoById(devicesTake.getDevicesTakeId());
		if(extisTake == null) {
			throw new ParametersException("印章外带记录不存在");
		}
		
		if(!extisTake.getCompanyId().equals(devicesTake.getCompanyId())) {
			throw new ParametersException("非法操作");
		}
		
		if(devicesTake.getTakeTime() == null) {
			devicesTake.setTakeTime(new Date());
		}
		
		
		DevicesQuery devicesQuery = new DevicesQuery();
		devicesQuery.setCompanyId(devicesTake.getCompanyId());
		devicesQuery.setDevicesId(devicesTake.getDevicesId());
		Devices devices = devicesMapper.selectInfoByQuery(devicesQuery);
		if(devices == null) {
			throw new ParametersException("设备不存在");
		}
		if(!devices.getDevicesStatus().equals(DevicesStatusEnum.ACTIVATE.code())) {
			throw new ParametersException("此设备还未激活");
		}
		if(!devices.getTakeStatus().equals(TakeStatusEnum.NORMAL.code())) {
			throw new ParametersException("此设备已被借出");
		}
		
		Apply apply = applyMapper.selectInfoById(extisTake.getApplyId());
		Seal seal = sealMapper.selectInfoById(extisTake.getSealId());
		
		transactionTemplate.execute(new TransactionCallbackWithoutResult() {
			
			@Override
			protected void doInTransactionWithoutResult(TransactionStatus status) {
				try {
					extisTake.setTakeTime(devicesTake.getTakeTime());
					extisTake.setTakeStatus(TakeStatusEnum.WAIT_RETURN.code());
					extisTake.setDevicesId(devicesTake.getDevicesId());
					devicesTakeMapper.update(extisTake);
					
					devices.setTakeStatus(TakeStatusEnum.WAIT_RETURN.code());
					devicesMapper.update(devices);
					
					
					
					
					
					seal.setInterimPartyId(apply.getPartyId());
					seal.setInterimExpiredDate(apply.getTakeEndTime());
					seal.setTakeStatus(TakeStatusEnum.PENDING.code());
					seal.setTakePartyId(apply.getPartyId());
					sealMapper.update(seal);
					
					Party party = partyMapper.selectByPrimaryKey(apply.getPartyId());
					
					//添加临时保管员记录
					Custos custos = new Custos();
					custos.setCustosType(CustosTypeEnum.TAKE.code());
					custos.setCompanyId(apply.getCompanyId());
					custos.setSealId(apply.getSealId());
					custos.setPartyId(apply.getPartyId());
					custos.setUserLoginId(party.getUserLoginId());
					custos.setDevicesId(apply.getDevicesId());
					custos.setCreateTime(new Date());
					custos.setCustosStatus(CustosStatusEnum.EFFECTIVE.code());
					custos.setRemark("申请外带成功");
					custosMapper.insert(custos);
					
					
					
					
				}catch (Exception e) {
					status.setRollbackOnly();
					throw e;
				}
				
			}
		});
	}
	@Override
	public void returns(DevicesTake devicesTake) {
		
		if(devicesTake == null) {
			throw new ParametersException("devicesTake is null");
		}
		
		if(devicesTake.getDevicesTakeId() == null) {
			throw new ParametersException("DevicesTakeId is null");
		}
		
		if(devicesTake.getDevicesId() == null) {
			throw new ParametersException("请选择设备");
		}
		
		DevicesTake extisTake = devicesTakeMapper.selectInfoById(devicesTake.getDevicesTakeId());
		if(extisTake == null) {
			throw new ParametersException("印章外带记录不存在");
		}
		
		if(!extisTake.getCompanyId().equals(devicesTake.getCompanyId())) {
			throw new ParametersException("非法操作");
		}
		
		if(devicesTake.getReturnTime() == null) {
			devicesTake.setReturnTime(new Date());
		}
		
		
		DevicesQuery devicesQuery = new DevicesQuery();
		devicesQuery.setCompanyId(devicesTake.getCompanyId());
		devicesQuery.setDevicesId(devicesTake.getDevicesId());
		Devices devices = devicesMapper.selectInfoByQuery(devicesQuery);
		if(devices == null) {
			throw new ParametersException("设备不存在");
		}
		if(!devices.getDevicesStatus().equals(DevicesStatusEnum.ACTIVATE.code())) {
			throw new ParametersException("此设备不处于激活状态");
		}
		if(!devices.getTakeStatus().equals(TakeStatusEnum.WAIT_RETURN.code())) {
			throw new ParametersException("此设备不处于借出状态");
		}
		
		Seal seal = sealMapper.selectInfoById(devices.getSealId());
		if(seal == null) {
			throw new ParametersException("此设备信息错误");
		}
		
		CustosQuery custosQuery = new CustosQuery();
		custosQuery.setSealId(seal.getSealId());
		custosQuery.setCompanyId(seal.getCompanyId());
		custosQuery.setCustosStatus(CustosStatusEnum.TEMPORARY_INVALID.getCode());
		custosQuery.setCustosType(CustosTypeEnum.INTERIM.getCode());
		Custos custos = custosMapper.selectInfoByQuery(custosQuery);
		long currentTime = LocalDateTime.of(LocalDate.now(), LocalTime.MIN).toInstant(ZoneOffset.of("+8")).toEpochMilli();
		if(custos != null) {
			if(custos.getExpireData() != null && 
					custos.getExpireData().getTime() >= currentTime) {
				custos.setCustosStatus(CustosStatusEnum.EFFECTIVE.getCode());
				custos.setRemark("设备归还临时管理员恢复");
				
				seal.setInterimPartyId(custos.getPartyId());
				seal.setInterimExpiredDate(custos.getExpireData());
			}else {
				custos.setCustosStatus(CustosStatusEnum.INVALID.getCode());
				custos.setRemark("临时管理员过期");
				
				seal.setInterimPartyId(null);
				seal.setInterimExpiredDate(null);
			}
		}else {
			seal.setInterimPartyId(null);
			seal.setInterimExpiredDate(null);
		}
		
		transactionTemplate.execute(new TransactionCallbackWithoutResult() {
			
			@Override
			protected void doInTransactionWithoutResult(TransactionStatus status) {
				try {
					extisTake.setReturnTime(devicesTake.getReturnTime());
					extisTake.setTakeStatus(TakeStatusEnum.RETURND.code());
					devicesTakeMapper.update(extisTake);
					
					devices.setTakeStatus(TakeStatusEnum.NORMAL.code());
					devicesMapper.update(devices);
					
					
					if(seal !=null) {
						sealMapper.updateInterim(seal);
					}
					
					if(custos != null) {
						custosMapper.update(custos);
					}
				}catch (Exception e) {
					status.setRollbackOnly();
					throw e;
				}
				
			}
		});
		
		
		
		
	}
}
